﻿Imports Microsoft.Win32

Partial Public Class MainWindow

#Region " Fields"
    ''' <summary>
    ''' This is the filename for the current script project
    ''' </summary>
    ''' <remarks></remarks>
    Private _filename As String
#End Region

#Region " Events"
    Private Sub RecentFileList_MenuClick(ByVal sender As System.Object, ByVal e As Common.RecentFileList.MenuClickEventArgs)
        Try
            ProcessOpen(e.Filepath)
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub

#Region " Scripts Drag Drop Events"
    Private Sub lbScripts_DragOver(ByVal sender As System.Object, ByVal e As System.Windows.DragEventArgs) Handles lbScripts.DragOver

        Dim canPerform As Boolean = False

        If Me.ScriptProject IsNot Nothing AndAlso Me.SelectedScriptGroup IsNot Nothing Then
            canPerform = e.Data.GetDataPresent(DataFormats.FileDrop)
        End If

        If canPerform Then
            'Deal with the effects
            e.Effects = e.AllowedEffects And DragDropEffects.Link
        End If
    End Sub

    Private Sub lbScripts_Drop(ByVal sender As System.Object, ByVal e As System.Windows.DragEventArgs) Handles lbScripts.Drop
        Try
            'Check to see if we have something
            If Me.ScriptProject Is Nothing Then
                Return
            End If

            'Make sure we have a group
            If Me.SelectedScriptGroup Is Nothing Then
                Return
            End If

            'Check to see if we got the filenames
            If e.Data.GetDataPresent(DataFormats.FileDrop) Then

                'Get the names of the files
                Dim filenames As String() = TryCast(e.Data.GetData(DataFormats.FileDrop), String())

                'This is the script
                Dim script As Script

                'Deal with each filename
                For Each filename As String In filenames

                    'Create the new script
                    script = New Script()

                    'Set the name of the script
                    script.Name = System.IO.Path.GetFileNameWithoutExtension(filename).Replace("dbo.", "")

                    'Set the filename (relative to the base path, of course)
                    script.FileName = GetRelativePath(filename)

                    'Set the type of the script
                    script.ScriptType = ScriptTypes.ScriptName

                    'Add the item to the 
                    Me.SelectedScriptGroup.Scripts.Add(script)

                Next

            End If

        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

    Private Sub BaseDirectoryButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles BaseDirectoryButton.Click
        Try
            ProcessBrowseForBaseDirectory()
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub

    Private Sub Window1_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
        Try
            'TODO: Encrypt the connect string
            'TODO: Give the user the option of saving te connect string
            'TODO: Hide the connection string from the user

            'Restore the connection string to the textbox
            ConnectionStringTextBox.Text = My.Settings.ConnectionString

            'Check to see if we have any command line args.  
            If Application.CommandLineArgs.Count > 0 Then

                'We do have a command line arg - open it up!
                ProcessOpen(Application.CommandLineArgs.Values.Cast(Of String).First)

            End If

            EnableButtons()
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub

    Private Sub Window1_Closed(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Closed
        Try
            My.Settings.ConnectionString = ConnectionStringTextBox.Text
            My.Settings.Save()
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub

    Private Sub Window1_Closing(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
        Try
            e.Cancel = Not SaveBeforeContinue()
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub

    Private Sub ExecuteAllScripts_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        Try
            ProcessExecuteAllScripts()
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub

    ''' <summary>
    ''' Forces a requery of command status.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub ConnectionStringTextBox_TextChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.TextChangedEventArgs) Handles ConnectionStringTextBox.TextChanged
        CommandManager.InvalidateRequerySuggested()
    End Sub

    Private Sub BrowseForScriptButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles BrowseForScriptButton.Click
        Try

            'Make sure that a script is selected
            If Me.SelectedScript IsNot Nothing Then

                'Create the dialog
                Dim dialog As New OpenFileDialog

                'Set the filter
                dialog.Filter = "All Files(*.*)|*.*"

                'Show the dialog
                Dim result As Boolean? = dialog.ShowDialog()

                'Check the result
                If result.HasValue AndAlso result.Value Then

                    'Save the new (relative) filename
                    Me.SelectedScript.FileName = GetRelativePath(dialog.FileName)

                End If
            End If

        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub

    Private Sub ScriptTypeCombo_SelectionChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs) Handles ScriptTypeCombo.SelectionChanged
        EnableButtons()
    End Sub

    Private Sub ScriptGrid_DataContextChanged(ByVal sender As System.Object, ByVal e As System.Windows.DependencyPropertyChangedEventArgs)
        EnableButtons()
    End Sub

    Private Sub BrowseForScriptDirectoryButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles BrowseForScriptDirectoryButton.Click
        Try
            ProcessBrowseForScriptDirectory()
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub

    Private Sub AboutMenuItem_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        Try
            Dim dialog As New AboutWindow()
            dialog.ShowDialog()
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub

    Private Sub OptionsMenuItem_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        Try
            Throw New Exception("Options not implemented yet")
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub

    Private Sub BaseDirectoryLink_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        Try
            If Not String.IsNullOrEmpty(BaseDirectoryTextBox.Text) Then

                If System.IO.Directory.Exists(BaseDirectoryTextBox.Text) Then
                    System.Diagnostics.Process.Start(BaseDirectoryTextBox.Text)
                Else
                    MessageBox.Show("Directory """ & BaseDirectoryTextBox.Text & """ does not exist")
                End If

            End If

        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub

    Private Sub FileLink_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        Try
            'TODO: Find the file (or display it)
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub

    Private Sub ScriptDirectoryLink_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        Try

        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

#Region " Methods"

    ''' <summary>
    ''' Navigates to the script that caused the exception.
    ''' </summary>
    ''' <param name="ex"></param>
    ''' <remarks></remarks>
    Private Sub HandleScriptLoadException(ByVal ex As ScriptLoadException)

        'Display the error information
        ex.Handle()

        Dim foundScriptGroup As ScriptGroup = Nothing
        Dim foundScript As Script = FindScript(ex.Script, foundScriptGroup)

        'Determine if we found the script
        If foundScript IsNot Nothing Then
            Me.SelectedScriptGroup = foundScriptGroup
            Me.SelectedScript = foundScript
        End If

    End Sub

    ''' <summary>
    ''' Finds a script
    ''' </summary>
    ''' <param name="scriptToSearchFor"></param>
    ''' <returns></returns>
    Private Function FindScript(ByVal scriptToSearchFor As Script, _
                                Optional ByRef foundGroup As ScriptGroup = Nothing) As Script

        'Check the arguments
        If scriptToSearchFor Is Nothing Then Throw New ArgumentNullException("scriptToSearchFor")

        'Search through each script group
        For Each scriptGroup As ScriptGroup In Me.ScriptProject.ScriptGroups
            For Each script As Script In scriptGroup.Scripts

                'Check to see if this is the one
                If script Is scriptToSearchFor Then

                    'Eureka - we found it!
                    foundGroup = scriptGroup
                    Return script

                End If
            Next
        Next

        'We didn't find it.  Return nothing.
        Return Nothing

    End Function

    ''' <summary>
    ''' Enables various UI elements according to the current state
    ''' </summary>
    ''' <remarks>
    ''' This could be done with more clever triggers in XAML, but that 
    ''' would likely require converters and all of that is a pain, so this is easier for the time being.
    ''' </remarks>
    Private Sub EnableButtons()

        'Project level
        BaseDirectoryButton.IsEnabled = Me.ScriptProject IsNot Nothing
        BaseDirectoryTextBox.IsEnabled = Me.ScriptProject IsNot Nothing

        'Script level
        ScriptGrid.IsEnabled = SelectedScript IsNot Nothing
        ScriptCommandTextTextBox.IsEnabled = SelectedScript IsNot Nothing AndAlso SelectedScript.ScriptType = ScriptTypes.CommandText
        ScriptFileNameTextBox.IsEnabled = SelectedScript IsNot Nothing AndAlso SelectedScript.ScriptType = ScriptTypes.ScriptName
        BrowseForScriptButton.IsEnabled = SelectedScript IsNot Nothing AndAlso SelectedScript.ScriptType = ScriptTypes.ScriptName

        BrowseForScriptDirectoryButton.IsEnabled = SelectedScript IsNot Nothing AndAlso SelectedScript.ScriptType = ScriptTypes.Directory
        ScriptDirectoryTextBox.IsEnabled = SelectedScript IsNot Nothing AndAlso SelectedScript.ScriptType = ScriptTypes.Directory
        ScriptFilterTextBox.IsEnabled = SelectedScript IsNot Nothing AndAlso SelectedScript.ScriptType = ScriptTypes.Directory

        'Window title
        If Me.ScriptProject Is Nothing Then

            'If we don't have anything loaded, then just use the project name
            Me.Title = Constants.ProductName

        Else

            Dim dirty As String = String.Empty

            'If dirty, then use the asterix
            If Me.IsDirty Then
                dirty = "*"
            End If

            'Set the title of the window
            Me.Title = String.Format("{0}{1} - {2}", _filename, dirty, Constants.ProductName)

        End If
    End Sub

    ''' <summary>
    ''' Saves the current document using a new name
    ''' </summary>
    ''' <returns>True if successful, false otherwise.</returns>
    Private Function ProcessSaveAs() As Boolean

        'Make sure that we have something to work with.
        If Me.ScriptProject Is Nothing Then
            Return False
        End If

        'Execute the action
        Dim result As Boolean = SaveAsAction.Execute(Me.ScriptProject, _filename)

        'Store the name of the project
        If result Then
            RecentFileList.InsertFile(_filename)
        End If

        Return result

    End Function

    ''' <summary>
    ''' Saves the current project
    ''' </summary>
    ''' <returns>True if successful, false otherwise.</returns>
    Private Function ProcessSave() As Boolean
        If String.IsNullOrEmpty(_filename) Then

            'We must save this as something
            Dim result As Boolean = ProcessSaveAs()

            Return result

        Else
            'Execute the action
            SaveAction.Execute(Me.ScriptProject, _filename)

            'Update the UI
            EnableButtons()

            RecentFileList.InsertFile(_filename)

            Return True
        End If
    End Function

    ''' <summary>
    ''' Gets a path that is relative to the BaseDirectory.
    ''' </summary>
    ''' <param name="rawPath"></param>
    ''' <returns></returns>
    Private Function GetRelativePath(ByVal rawPath As String) As String

        Dim directory As String

        If String.IsNullOrEmpty(Me.ScriptProject.Options.BaseDirectory) Then

            'There is no base path - just use the raw selected path from the options
            directory = rawPath
        Else

            Dim fullSelectedPath As String = IO.Path.GetFullPath(rawPath)
            Dim fullBasePath As String = IO.Path.GetFullPath(Me.ScriptProject.Options.BaseDirectory)

            'Assumption: I'm assuming that this will work because the path should start with the volume (e.g. "c:\")
            directory = fullSelectedPath.Replace(fullBasePath, Nothing)

            'Make sure that we've got something to work with
            If directory.Length > 0 Then

                'Determine if the first character is a directory separator
                If directory(0) = IO.Path.DirectorySeparatorChar Then

                    'Remove the first charecter
                    directory = directory.Remove(0, 1)

                End If

            End If

        End If

        'Return our work
        Return directory
    End Function

    ''' <summary>
    ''' Gets the directory for the script
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub ProcessBrowseForScriptDirectory()

        'Check to see if we should really be doing this
        If Me.ScriptProject Is Nothing OrElse Me.SelectedScript Is Nothing Then
            Return
        End If

        'Use the old windows forms folder browser dialog (might be nice to upgrade this one day)
        Using dialog As New System.Windows.Forms.FolderBrowserDialog

            Dim startPath As String = Nothing

            'Check to see if we hav a directory for this script already
            If String.IsNullOrEmpty(Me.SelectedScript.Directory) Then

                'Check to see if there is base directory
                If Not String.IsNullOrEmpty(Me.ScriptProject.Options.BaseDirectory) Then

                    'Use the base directory for the project
                    startPath = Me.ScriptProject.Options.BaseDirectory

                End If

            Else

                'Check to see if we have a base directory
                If Not String.IsNullOrEmpty(Me.ScriptProject.Options.BaseDirectory) Then

                    'We do - just use the base directory
                    startPath = Me.ScriptProject.Options.BaseDirectory

                End If
            End If

            'Check to see if we have any kind of start path
            If Not String.IsNullOrEmpty(startPath) AndAlso IO.Directory.Exists(startPath) Then

                'Set the start path for the dialog
                dialog.SelectedPath = startPath

            End If

            'Show the dialog
            If dialog.ShowDialog = Forms.DialogResult.OK Then

                'Update the business object
                Me.SelectedScript.Directory = GetRelativePath(dialog.SelectedPath)

            End If

        End Using

    End Sub

    ''' <summary>
    ''' Browses for the base direrectory that will be used to execute scripts
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub ProcessBrowseForBaseDirectory()

        'Make sure that we have something to work with.
        If Me.ScriptProject Is Nothing OrElse Me.ScriptProject.Options Is Nothing Then
            Return
        End If

        'Create the dialog.  We're using the old Windows Forms FolderBrowserDialog
        'Maybe we'll look at a later date to include the CodePlex WPF version.
        Using dialog As New System.Windows.Forms.FolderBrowserDialog

            'Check to see if we already have a base directory (and if we do that it exists)
            If Not String.IsNullOrEmpty(Me.ScriptProject.Options.BaseDirectory) AndAlso _
                IO.Directory.Exists(Me.ScriptProject.Options.BaseDirectory) Then

                'Start out the dialog with the specified directory
                dialog.SelectedPath = Me.ScriptProject.Options.BaseDirectory
            End If

            'Show the dialog
            If dialog.ShowDialog = Forms.DialogResult.OK Then

                'Update the options
                Me.ScriptProject.Options.BaseDirectory = dialog.SelectedPath
            End If

        End Using

    End Sub

    ''' <summary>
    ''' Opens a project
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub ProcessOpen()

        'Check to see if the user wants to save what's currently loaded
        If SaveBeforeContinue() Then

            'We're good
            Dim project As ScriptProject = Nothing
            Dim filename As String = Nothing

            'Execute the action.  Note that project and filename are passed
            ' by reference.
            If OpenAction.Execute(project, filename) Then

                'Save the script project.
                Me.ScriptProject = project

                'Save the filenames
                _filename = filename

                'Update the UI
                EnableButtons()

                'Add to the MRU
                RecentFileList.InsertFile(_filename)

            End If

        End If
    End Sub

    ''' <summary>
    ''' Opens the specified file.
    ''' </summary>
    ''' <param name="filename"></param>
    ''' <remarks></remarks>
    Private Sub ProcessOpen(ByVal filename As String)

        Try
            'Check to see if the user wants to save what's currently loaded
            If SaveBeforeContinue() Then

                'We're good
                Dim project As ScriptProject = Nothing

                'Execute the action.  Note that project and filename are passed
                ' by reference.
                If OpenAction.Execute(project, filename) Then

                    'Save the script project.
                    Me.ScriptProject = project

                    'Save the filenames
                    _filename = filename

                    'Update the UI
                    EnableButtons()

                    'Add to the MRU
                    RecentFileList.InsertFile(_filename)

                End If

            End If

        Catch ex As IO.FileNotFoundException
            'Get rid of this guy
            RecentFileList.RemoveFile(_filename)
        Catch
            Throw
        End Try
    End Sub

    ''' <summary>
    ''' Executes all scripts in the project
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub ProcessExecuteAllScripts()


        'Make sure that we have a project to work with
        If Me.ScriptProject Is Nothing Then
            Return
        End If

        'Make sure that we have some script groups.
        If Me.ScriptProject.ScriptGroups.Count = 0 Then
            Return
        End If

        'TODO: Check to see if there are any scripts at to work with.

        'Make sure the user is all in
        If MessageBox.Show("Are you sure you want to run ALL scripts?", _
                           "Run all scripts", _
                           MessageBoxButton.YesNo, _
                           MessageBoxImage.Question, _
                           MessageBoxResult.No) = MessageBoxResult.Yes Then

            Try

            

                'We will aggregate the scripts here
                Dim scripts As New List(Of Script)

                'Consider each group
                For Each scriptGroup As ScriptGroup In Me.ScriptProject.ScriptGroups

                    'Consider each script in this group
                    For Each script As Script In scriptGroup.Scripts

                        'Add this script to the list
                        scripts.Add(script)
                    Next
                Next

                'Go ahead and run the scripts
                ExecuteAction.Execute(Me.ScriptProject, _
                                      scripts, _
                                      ConnectionStringTextBox.Text)

            Catch ex As ScriptLoadException
                HandleScriptLoadException(ex)
            End Try

        End If
    End Sub

    ''' <summary>
    ''' If the current project is dirty, asks the user to save before proceeding.
    ''' </summary>
    ''' <returns>True to continue, False to cancel</returns>
    Private Function SaveBeforeContinue() As Boolean

        'If we don't have a project, it doesn't matter
        If Me.ScriptProject Is Nothing Then
            Return True
        End If

        'If we're not dirty, than it doesn't matter
        If Not IsDirty Then

            'Save the options anyway
            Me.ScriptProject.SaveOptions(_filename)

            Return True
        End If

        Dim msg As String = String.Format("Project '{0}' has changed." & Environment.NewLine & Environment.NewLine & "Do you want to save changes?", _filename)

        'Ask the user
        Dim result As MessageBoxResult = MessageBox.Show(msg, _
                                                         "Script Runner", _
                                                         MessageBoxButton.YesNoCancel, _
                                                         MessageBoxImage.Exclamation)

        'From this point on, this will store the result
        Dim shouldContinue As Boolean

        Select Case result
            Case MessageBoxResult.Yes

                'Save it
                shouldContinue = ProcessSave()

            Case MessageBoxResult.No

                'Save the options even though we're not saving the main file
                Me.ScriptProject.SaveOptions(_filename)

                'We can continue, the user doesn't want to save.
                shouldContinue = True

            Case MessageBoxResult.Cancel

                'Just in case
                Throw New InvalidOperationException(String.Format("Unexpected result from the messagebox - {0}", result))
        End Select

        'Return the result
        Return shouldContinue

    End Function
#End Region

#Region " Properties"
    ''' <summary>
    ''' Gets a valude indicating whether the project is dirty or not.
    ''' </summary>
    ''' <value></value>
    ''' <remarks></remarks>
    Private ReadOnly Property IsDirty() As Boolean
        Get
            If Me.ScriptProject Is Nothing Then
                Return False
            Else
                Return Me.ScriptProject.IsDirty
            End If
        End Get
    End Property

    ''' <summary>
    ''' Gets or sets the currently selected script project.
    ''' </summary>
    ''' <value></value>
    ''' <remarks></remarks>
    Private Property ScriptProject() As ScriptProject
        Get
            Return DirectCast(Me.DataContext, ScriptProject)
        End Get
        Set(ByVal value As ScriptProject)
            Me.DataContext = value
        End Set
    End Property

    ''' <summary>
    ''' Gets the currently selected scripts
    ''' </summary>
    ''' <value></value>
    ''' <remarks></remarks>
    Private ReadOnly Property SelectedScripts() As IEnumerable(Of Script)
        Get
            Return Me.lbScripts.SelectedItems.Cast(Of Script)()
        End Get
    End Property

    ''' <summary>
    ''' Gets or sets the currently selected script.
    ''' </summary>
    ''' <value></value>
    ''' <remarks></remarks>
    Private Property SelectedScript() As Script
        Get
            Return DirectCast(lbScripts.SelectedItem, Script)
        End Get
        Set(ByVal value As Script)
            lbScripts.SelectedItem = value
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets the currentl selected script group.
    ''' </summary>
    ''' <value></value>
    ''' <remarks></remarks>
    Private Property SelectedScriptGroup() As ScriptGroup
        Get
            Return DirectCast(lbScriptGroups.SelectedItem, ScriptGroup)
        End Get
        Set(ByVal value As ScriptGroup)
            lbScriptGroups.SelectedItem = value
        End Set
    End Property
#End Region

#Region " Command Bindings"

#Region " Open"
    Private Sub Open_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
        e.CanExecute = True
    End Sub

    Private Sub Open_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Try
            ProcessOpen()
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

#Region " Execute All"
    Private Sub ExecuteAll_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
        e.CanExecute = Me.ScriptProject IsNot Nothing AndAlso Me.ScriptProject.ScriptGroups.Count > 0
    End Sub

    Private Sub ExecuteAll_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Try
            ProcessExecuteAllScripts()
        
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

#Region " Execute Script (Single Script)"
    Private Sub ExecuteScript_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
        e.CanExecute = Me.SelectedScripts.Count() > 0
    End Sub

    Private Sub ExecuteScript_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Try
            Dim scripts = Me.SelectedScripts

            If scripts.Count() > 0 Then
                ExecuteAction.Execute(Me.ScriptProject, _
                                  scripts, _
                                  ConnectionStringTextBox.Text)
            End If

            

        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

#Region " ExecuteScriptGroup"
    Private Sub ExecuteScriptGroup_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
        e.CanExecute = Me.SelectedScriptGroup IsNot Nothing
    End Sub

    Private Sub ExecuteScriptGroup_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Try
            ExecuteAction.Execute(Me.ScriptProject, _
                                  Me.SelectedScriptGroup.Scripts, _
                                  ConnectionStringTextBox.Text)
        Catch ex As ScriptLoadException
            HandleScriptLoadException(ex)
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

#Region " Save"
    Private Sub Save_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
        e.CanExecute = SaveAction.CanExecute(Me.ScriptProject)
    End Sub

    Private Sub Save_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Try
            ProcessSave()
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

#Region " New"
    Private Sub New_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
        e.CanExecute = True
    End Sub

    Private Sub New_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Dim project As New ScriptProject()

        Me.ScriptProject = project
    End Sub
#End Region

#Region " SaveAs"
    Private Sub SaveAs_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
        e.CanExecute = SaveAsAction.CanExecute(Me.ScriptProject)
    End Sub

    Private Sub SaveAs_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Try
            SaveAsAction.Execute(Me.ScriptProject, _filename)
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

#Region " Close"
    Private Sub Close_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)

    End Sub

    Private Sub Close_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)

    End Sub
#End Region

#Region " MoveScriptUp"
    Private Sub MoveScriptUp_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)

        e.CanExecute = lbScripts IsNot Nothing _
                        AndAlso lbScripts.SelectedIndex > 0

    End Sub

    Private Sub MoveScriptUp_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Try
            Me.SelectedScriptGroup.Scripts.Move(lbScripts.SelectedIndex, lbScripts.SelectedIndex - 1)
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

#Region " MoveScriptDown"
    Private Sub MoveScriptDown_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)

        e.CanExecute = lbScripts IsNot Nothing _
                        AndAlso lbScripts.SelectedIndex > -1 _
                        AndAlso lbScripts.SelectedIndex < lbScripts.Items.Count - 1


    End Sub

    Private Sub MoveScriptDown_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Try
            Me.SelectedScriptGroup.Scripts.Move(lbScripts.SelectedIndex, lbScripts.SelectedIndex + 1)
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

#Region " MoveScriptToTop"
    Private Sub MoveScriptToTop_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
        e.CanExecute = lbScripts IsNot Nothing _
                        AndAlso lbScripts.SelectedIndex > 0
    End Sub

    Private Sub MoveScriptToTop_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Try
            Me.SelectedScriptGroup.Scripts.Move(lbScripts.SelectedIndex, 0)
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

#Region " MoveScriptDown"
    Private Sub MoveScriptToBottom_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
        e.CanExecute = lbScripts IsNot Nothing _
                      AndAlso lbScripts.SelectedIndex > -1 _
                      AndAlso lbScripts.SelectedIndex < lbScripts.Items.Count - 1
    End Sub

    Private Sub MoveScriptToBottom_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Try
            Me.SelectedScriptGroup.Scripts.Move(lbScripts.SelectedIndex, lbScripts.Items.Count - 1)
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

#Region " DeleteScript"
    Private Sub DeleteScript_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
        e.CanExecute = Me.SelectedScript IsNot Nothing
    End Sub

    Private Sub DeleteScript_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Try

            'Check to see if we have something to work with
            If Me.SelectedScript Is Nothing Then Return
            If Me.SelectedScriptGroup Is Nothing Then Return

            'Craft the message
            Dim msg As String = String.Format("Delete Script '{0}' - are you sure?", Me.SelectedScript.Name)

            'Show the message
            If MessageBox.Show(msg, _
                               "Delete", _
                               MessageBoxButton.YesNo, _
                               MessageBoxImage.Question) = MessageBoxResult.Yes Then

                'Remove the selected script group
                Me.SelectedScriptGroup.Scripts.Remove(Me.SelectedScript)

            End If

        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

#Region " MoveScriptGroupUp"
    Private Sub MoveScriptGroupUp_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
        e.CanExecute = lbScriptGroups IsNot Nothing _
                        AndAlso lbScriptGroups.SelectedIndex > 0
    End Sub

    Private Sub MoveScriptGroupUp_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Try
            Me.ScriptProject.ScriptGroups.Move(lbScriptGroups.SelectedIndex, lbScriptGroups.SelectedIndex - 1)
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

#Region " MoveScriptGroupDown"
    Private Sub MoveScriptGroupDown_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
        e.CanExecute = lbScriptGroups IsNot Nothing _
                        AndAlso lbScriptGroups.SelectedIndex > -1 _
                        AndAlso lbScriptGroups.SelectedIndex < lbScripts.Items.Count - 1

    End Sub

    Private Sub MoveScriptGroupDown_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Try
            Me.ScriptProject.ScriptGroups.Move(lbScriptGroups.SelectedIndex, lbScriptGroups.SelectedIndex + 1)
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

#Region " DeleteScriptGroup"
    Private Sub DeleteScriptGroup_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
        e.CanExecute = Me.SelectedScriptGroup IsNot Nothing
    End Sub

    Private Sub DeleteScriptGroup_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Try

            'Check to see if we have something to work with
            If Me.SelectedScriptGroup Is Nothing Then Return

            'Craft the message
            Dim msg As String = String.Format("Delete Script Group '{0}' - are you sure?", Me.SelectedScriptGroup.Name)

            'Show the message
            If MessageBox.Show(msg, _
                               "Delete", _
                               MessageBoxButton.YesNo, _
                               MessageBoxImage.Question) = MessageBoxResult.Yes Then

                'Remove the selected script group
                Me.ScriptProject.ScriptGroups.Remove(Me.SelectedScriptGroup)

            End If

        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

#Region " ScriptInsert"
    Private Sub ScriptInsert_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
        e.CanExecute = Me.SelectedScriptGroup IsNot Nothing
    End Sub

    Private Sub ScriptInsert_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Try
            'Ask the user for the name of the new script
            Dim dialog As New TextDialog("Name", "New Script Name", True, "")

            'Show the dialog
            Dim result As Boolean? = dialog.ShowDialog()

            'Check to see if the user clicked OK
            If result.HasValue AndAlso result.Value Then

                'Create the new script
                Dim script As New Script() With {.Name = dialog.UserText, .CommandText = dialog.UserText, .ScriptType = ScriptTypes.CommandText}

                'Determine if a script is already selected
                If lbScripts.SelectedIndex > -1 Then

                    'Insert the script by the selected script (instead of just adding it to the end)
                    Me.SelectedScriptGroup.Scripts.Insert(lbScripts.SelectedIndex, script)
                Else

                    'Nothing is selected, just add it to the end of the list
                    Me.SelectedScriptGroup.Scripts.Add(script)
                End If

                'Select this script
                Me.SelectedScript = script
            End If
        Catch ex As Exception

        End Try
    End Sub
#End Region

#Region " ScriptGroupInsert"
    Private Sub ScriptGroupInsert_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
        e.CanExecute = Me.ScriptProject IsNot Nothing
    End Sub

    Private Sub ScriptGroupInsert_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Try
            'Ask the user for the name of the script group
            Dim dialog As New TextDialog("Name", "New Script Group", True, "")

            'Show the dialog
            Dim result As Boolean? = dialog.ShowDialog()

            'Check to see if the user clicked OK
            If result.HasValue AndAlso result.Value Then

                'Create the new script group
                Dim scriptGroup As New ScriptGroup() With {.Name = dialog.UserText}

                'Add the script group to the current project
                Me.ScriptProject.ScriptGroups.Add(scriptGroup)

                'Select the new script group.
                Me.SelectedScriptGroup = scriptGroup
            End If
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

#Region " Rename Script Group"
    Private Sub RenameScriptGroup_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
        e.CanExecute = RenameAction.CanExecute(Me.SelectedScriptGroup)
    End Sub

    Private Sub RenameScriptGroup_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Try
            RenameAction.Execute(Me.SelectedScriptGroup)
        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

#Region " Move Scripts"
    Private Sub Scripts_Move_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
        e.CanExecute = Me.ScriptProject IsNot Nothing AndAlso _
                    Me.ScriptProject.ScriptGroups.Count >= 2 _
                    AndAlso Me.SelectedScripts.Count > 0 _
                    AndAlso Me.SelectedScriptGroup IsNot Nothing
    End Sub

    Private Sub Scripts_Move_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
        Try

            'Get all of the groups (except for the one that is selected)
            Dim groups = From item In Me.ScriptProject.ScriptGroups _
                         Where item IsNot Me.SelectedScriptGroup

            'Create the dialog
            Dim dialog As New SelectScriptGroupDialog(groups)

            'Show the dialog
            Dim result = dialog.ShowDialog()

            'Examine the result
            If result.HasValue AndAlso result.Value Then

                'Get the selected group
                Dim selectedGroup As ScriptGroup = dialog.SelectedGroup

                'Make sure that we got something
                If selectedGroup IsNot Nothing Then

                    'Consider each script that the user has selected
                    For Each item In Me.SelectedScripts.ToArray()

                        'Add the item to the other collection
                        selectedGroup.Scripts.Add(item)

                        'Remove the item from the original list
                        Me.SelectedScriptGroup.Scripts.Remove(item)

                    Next

                    'Select the group
                    Me.SelectedScriptGroup = selectedGroup

                End If

            End If

        Catch ex As Exception
            ex.Handle()
        End Try
    End Sub
#End Region

#End Region

   
   
End Class
